#include "linked_list.h"
#include "thread_pool.h"
#include "user.h"
#define INITIAL_BUFFER_SIZE 4096
//外部变量(userList是在main.c文件中定义的)
extern ListNode * userList;

//主线程调用:处理客户端发过来的消息
void handleMessage(int sockfd, int epfd, task_queue_t * que,MYSQL* conn)
{
    printf("execute handleMessage()\n");
    //消息格式：cmd content
    //1.1 获取消息长度
    int length = -1;
    int ret = recvn(sockfd, &length, sizeof(length));
    if(ret == 0) {
        goto end;
    }
    printf("\n\nrecv length: %d\n", length);

    //1.2 获取消息类型
    int cmdType = -1;
    ret = recvn(sockfd, &cmdType, sizeof(cmdType));
    if(ret == 0) {
        goto end;
    }
    printf("recv cmd type: %d\n", cmdType);
    
    task_t *ptask = (task_t*)calloc(1, sizeof(task_t));
    ptask->peerfd = sockfd;
    ptask->epfd = epfd;
    ptask->type= cmdType;
    if(length > 0) {
        printf("before recv\n");
        printf("sockfd:%d\n",sockfd);
        printf("length: %d\n",length);
        //1.3 获取消息内容
        ret = recvn(sockfd, ptask->data, length);
        printf("recv content: %s\n", ptask->data);
        if(ret > 0) {
            //往任务队列中中添加任务
            if(ptask->type == REGISTER_REQUEST){
                taskEnque(que,ptask);
            }else if(ptask->type == CMD_TYPE_PUTS) {
                //是上传文件任务，就暂时先从epoll中删除监听
                delEpollReadfd(epfd, sockfd);
            }else{
                taskEnque(que, ptask);
            }
        }
    } else if(length == 0){
        taskEnque(que, ptask);
    }
end:
    if(ret == 0) {//连接断开的情况
        printf("\nconn %d is closed.\n", sockfd);
        delEpollReadfd(epfd, sockfd);
        close(sockfd);
        deleteNode2(&userList, sockfd);//删除用户信息
    }
}

//注意：此函数可以根据实际的业务逻辑，进行相应的扩展
//子线程调用
void doTask(task_t * task,MYSQL* conn)
{
    printf("execute doTask\n");
    assert(task);
    switch(task->type) {
    printf("execute Command\n");
    case CMD_TYPE_PWD:  
    printf("execute pwdCommand\n");
        pwdCommand(task);   break;
    case CMD_TYPE_CD:
    printf("execute cdCommand\n");
        cdCommand(task);    break;
    case CMD_TYPE_LS:
    printf("execute lsCommand\n");
        lsCommand(task);    break;
    case CMD_TYPE_MKDIR:
    printf("execute mkdirCommand\n");
        mkdirCommand(task);  break;
    case CMD_TYPE_RMDIR:
    printf("execute rmdirCommand\n");
        rmdirCommand(task);  break;
    case CMD_TYPE_NOTCMD:
    printf("execute notCommand\n");
        notCommand(task);   break;
    case CMD_TYPE_PUTS:
    printf("execute putsCommand\n");
        putsCommand(task);   break;
    case CMD_TYPE_GETS:
    printf("execute getsCommand\n");
        getsCommand(task);   break;
    case TASK_LOGIN_SECTION1:
    printf("execute userLoginCheck1\n");
        userLoginCheck1(task); break;
    case TASK_LOGIN_SECTION2:
    printf("execute userLoginCheck2\n");
        userLoginCheck2(task); break;
    case REGISTER_REQUEST:
    printf("execute registerTaskHandler\n");
        registerTaskHandler(task,conn);break;
    case LOGIN_TASK:
    printf("execute loginTaskHandler\n");
        loginTaskHandler(task,conn);break;
    }
}

//每一个具体任务的执行，交给一个成员来实现

void showFileAll(task_t * task)
{
    printf("execute ls command.\n");

    // 定义参数
    DIR* pdir;
    char dir_path[1024] = {0};
    struct dirent* entry;
    size_t buffer_size = INITIAL_BUFFER_SIZE;
    size_t offset = 0;
    char* buffer = (char*)malloc(buffer_size);

    if (buffer == NULL) {
        perror("malloc");
        return;
    }

    // 打开目录
    if (strlen(task->data) == 0) {
        if (getcwd(dir_path, sizeof(dir_path)) == NULL) {
            perror("getcwd");
            free(buffer);
            return;
        }
    }
    else {
        strncpy(dir_path, task->data, sizeof(dir_path) - 1);
    }
    pdir = opendir(dir_path);
    if (pdir == NULL) {
        perror("opendir");
        free(buffer);
        return;
    }

    // 读取目录内容并存储到缓冲区
    while ((entry = readdir(pdir)) != NULL) {
        int len = snprintf(NULL, 0, "%s ", entry->d_name) + 1;
        if (offset + len + 1 > buffer_size) {
            // 增加缓冲区大小
            buffer_size *= 2;
            char* new_buffer = (char*)realloc(buffer, buffer_size);
            if (new_buffer == NULL) {
                perror("realloc");
                closedir(pdir);
                free(buffer);
                return;
            }
            buffer = new_buffer;
        }
        snprintf(buffer + offset, buffer_size - offset, "%s ", entry->d_name);
        offset += len - 1;
    }

    // 发送缓冲区内容
    //if (send(task->peerfd, buffer, offset, 0) < 0) {
    //    perror("send");
    // }
    printf("%s\n", buffer);

    closedir(pdir);
    free(buffer);
}
void cdCommand(task_t * task)
{
    printf("execute cd command.\n");
    ListNode* curuser = userList;
    char buff[128]={0};
    strcpy(buff,task->data);
    char cwd[128]={0};
    getcwd(cwd,sizeof(cwd));
    printf("cd 之前的cwd是：%s\n",cwd);

    int ret= chdir(buff);
    if(ret==-1){
        sendn(task->peerfd,"Bad address",11);
        return;
    }
    getcwd(cwd,sizeof(cwd));
    printf("cd 之后的cwd是：%s\n",cwd);
    strcpy(((user_info_t*)curuser->val)->pwd,cwd);
    sendn(task->peerfd,buff,sizeof(buff));

}


void mkdirCommand(task_t * task)
{
    printf("execute mkdir command.\n");
    if (mkdir(task->data, 0777) == 0) {
        train_t t;
        memset(&t, 0, sizeof(t));
        strcpy(t.buff, "mkdir successful.\n");
        sendn(task->peerfd, &t, strlen(t.buff));
    }
    else {
        perror("mkdir");
        train_t t;
        memset(&t, 0, sizeof(t));
        strcpy(t.buff, "mkdir failed.\n");
        sendn(task->peerfd, &t, strlen(t.buff));
    }
}

void rmdirCommand(task_t * task)
{
    printf("execute rmdir command.\n");
    if (rmdir(task->data) == 0) {
        train_t t;
        memset(&t, 0, sizeof(t));
        strcpy(t.buff, "rmdir successful.\n");
        sendn(task->peerfd, &t, strlen(t.buff));
    }
    else {
        perror("rmdir");
        train_t t;
        memset(&t, 0, sizeof(t));
        strcpy(t.buff, "rmdir failed.\n");
        sendn(task->peerfd, &t, strlen(t.buff));
    }
}

void notCommand(task_t * task)
{
    printf("execute not command.\n");
}


void getsCommand(task_t * task) {
    // 获取当前用户信息
    ListNode * pNode = userList;
    user_info_t * user = NULL;
    while (pNode != NULL) {
        user_info_t * temp = (user_info_t *)pNode->val;
        if (temp->sockfd == task->peerfd) {
            user = temp;
            break;
        }
        pNode = pNode->next;
    }

    if (user == NULL) {
        printf("User not found.\n");
        return;
    }

    // 生成完整文件路径
    char filepath[256];
    snprintf(filepath, sizeof(filepath), "%s/%s", user->pwd, task->data);

    // 打开文件
    int fd = open(filepath, O_RDONLY);
    if (fd == -1) {
        perror("open");
        return;
    }

    // 读取文件并发送
    char buffer[1024];
    ssize_t bytes_read;
    while ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0) {
        ssize_t bytes_sent = send(task->peerfd, buffer, bytes_read, 0);
        if (bytes_sent == -1) {
            perror("send");
            close(fd);
            return;
        }
    }

    if (bytes_read == -1) {
        perror("read");
    }

    close(fd);
}

//  void getsCommand(task_t * task) {
//    printf("execute gets command.\n");
//
//    printf("客户端传来的文件名是：%s\n",task->data);
//    //获取文件名
//    char filename[20] = {0};
//    strcpy(filename,task->data);
//    //获取文件名长度
//    printf("filename:%s\n",filename);
//    off_t len = 0;
//    //获取文件大小
//    int ret = recvn(task->peerfd,&len,sizeof(len));
//    printf("filelen: %ld.\n",len);
//    
//    //打开文件
//    int fd = open(filename,O_RDWR,0666);
//    if(fd<0){
//        perror("open");return;
//    }
//    //发送文件
//    char buff[1000]={0};
//    off_t left = len; //left表示待发送的字节数
//    ret = read(fd,buff,len);
//    
//    while(left > len){//循环发送文件内容，直到待发送的字节数为0
//        if(left < 1000){//当待发送的长度小于buff容量1000时
//            ret = sendn(task->peerfd,buff,left);//一次性发送buff过去
//        }else{
//            ret = sendn(task->peerfd,buff,sizeof(buff));//每次只发送buff大小字节数
//        }
//        if(ret < 0){//当发送的字节数为负数时，说明发生了发送错误，退出循环
//            break;
//        }
//
//        left-=ret;
//    }
//    //关闭文件描述符
//    close(fd);
//    //下载任务执行完毕之后再加回来,继续监听该客户端是否有新任务
//    addEpollReadfd(task->epfd,task->peerfd);
//
//    //判断客户端传过来的内容是否含有文件大小，如果含有，说明需要断点续传
//
//    //如果没有，则直接send该文件给客户端
//    //判断文件大小是否大于100M
//    //如果大于100M则使用mmap映射该文件，然后再传输
//    //如果不大于100M则不映射正常传输
//}




void userLoginCheck1(task_t * task) {
    printf("userLoginCheck1.\n");
    ListNode * pNode = userList;
    while(pNode != NULL) {
        user_info_t * user = (user_info_t *)pNode->val;
        if(user->sockfd == task->peerfd) {
            //拷贝用户名
            strcpy(user->name, task->data);
            loginCheck1(user);
            return;
        }
        pNode = pNode->next;
    }
}

void userLoginCheck2(task_t * task) {
    printf("userLoginCheck2.\n");
    ListNode * pNode = userList;
    while(pNode != NULL) {
        user_info_t * user = (user_info_t *)pNode->val;
        if(user->sockfd == task->peerfd) {
            //拷贝加密密文
            loginCheck2(user, task->data);
            //默认先chdir到useDir目录
            char cwd[128] = "/home/cj/opanel/userDir";
            strcat(cwd,"/");
            strcat(cwd,user->name);
            printf("cwd before chdir = %s\n",user->pwd);

            if(strcmp(user->pwd,"")!=0){//表示该用户不是第一次登录，
                chdir(cwd);
                printf("用户非第一次登录时，cwd after chdir = %s\n",getcwd(NULL,NULL));
            }else{//表示用户为第一次登录
                mode_t mode = 0666;
                mkdir(cwd,mode);
                chdir(cwd);
                printf("用户第一次登录时，cwd after chdir = %s\n",getcwd(NULL,NULL));

            }

            //重新初始化为当前路径
            strcpy(user->pwd,cwd);
            return;
        }
        pNode = pNode->next;
    }
}
